package com.atguigu.utils;


import cn.hutool.core.collection.ListUtil;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

@FunctionalInterface
interface Foo<T>{
    public String give(T val);
}

@FunctionalInterface
interface Foo2{
    public int give(String s1,String s2);
}

@FunctionalInterface
interface Foo3<R> {
    public R build(Integer id,String name,Integer age);
}

@Setter
@Getter
@NoArgsConstructor
class Person{
    private Integer id;
    private String personName;
    private Integer age;

    public Person(Integer id) {
        this.id = id;
    }

    public Person(Integer id, String personName, Integer age) {
        this.id = id;
        this.personName = personName;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", personName='" + personName + '\'' +
                ", age=" + age +
                '}';
    }
}



public class MethodRefDemo {

    public static void main(String[] args) {
        List<Integer> list = ListUtil.toList(11, 12, 13);

        List<Person> personList = list.stream().map(id -> new Person(id)).collect(Collectors.toList());
        personList.forEach(System.out::println);

        personList = list.stream().map(Person::new).collect(Collectors.toList());
        personList.forEach(System.out::println);
    }
    private static void test3(){
        //3 类名::实例方法（函数式接口抽象方法的第一个参数是实例方法的调用者，后面的参数是实例方法的参数）
        Person p1 = new Person(1, "z3", 13);
        Person p2 = new Person(2, "z4", 14);
        Person p3 = new Person(3, "z5", 15);
        ArrayList<Person> list = ListUtil.toList(p1, p2, p3);

        //3.1使用Lambda(第一个参数是实例方法的调用者，第一个参数person是getPersonName的调用者，自己持有)
        List<String> nameString = list.stream().map(person -> person.getPersonName()).collect(Collectors.toList());
        System.out.println(("使用Lambda:" + nameString));
        //3.2使用方法引用
        nameString = list.stream().map(Person::getPersonName).collect(Collectors.toList());
        System.out.println(("使用方法引用：" + nameString));

        //3.类名::实例方法(函数式接口抽象方法的第一个参数是实例方法的调用者，后面的参数是实例方法的参数)
        BiPredicate<String, String> biPredicate =(x,y)->x.equals(y);
        System.out.println(biPredicate.test("a", "a"));
       biPredicate =String::equals;
        System.out.println((biPredicate.test("a", "b")));
    }

    //2 类名::静态方法
    private static void test2(){
        //2 类名::静态方法
        List<Integer> list = ListUtil.toList(21, 2, -3);

        //2.1使用lambda
        list.sort((x,y)->x.compareTo(y));
        System.out.println(list);

        //2.2使用方法引用
        list=ListUtil.toList(21,2,-3);
        list.sort(Integer::compareTo);
        System.out.println(list);
    }

    //1对象::实例方法
    private static void test1(){
        //1.对象::实例方法
        List<Integer> list = ListUtil.toList(1, 2, 3);
        //1.1使用lambda
        list.forEach(i->System.out.println(i));
        //1.2使用方法引用
        list.forEach(System.out::println);
    }

    private static void AllCode()
    {
        System.out.println("通过方法引用，函数式接口不再需要程序员自己编写接口实现，而是通过已有的" +
                "方法引用形式来实现具体函数的实现,即methodA正好是lambda体的实现逻辑");
        System.out.println("");

        Foo<Integer> result = x ->(x*2)+"";
        System.out.println(("lambda express result: " + result.give(5)));

        result = String::valueOf;
        System.out.println(("1静态方法引用：" + result.give(10)));

        String str = "A";
        result = str::repeat;
        System.out.println(("2某个对象的方法引用： " + result.give(5)));

        Foo2 result2 = String::compareTo;
        System.out.println(("3特定类的方法引用： " + result2.give("z", "a")));
        result2 = (x,y)->{
            if (x.compareTo(y)>0){
                return  1;
            }else if (x.compareTo(y)<0){
                return -1;
            }else {
                return 0;
            }
        };
        System.out.println((result2.give("a", "a")));

        Foo3<Person> foo3 = Person::new;
        System.out.println(("4构造方法引用:" + foo3.build(11, "z3", 25)));


    }

}
